# -*- coding:utf-8 -*-
import uuid
from typing import Optional, Union

from apscheduler.jobstores.base import JobLookupError
from fastapi import APIRouter, HTTPException
from loguru import logger

from scheduler import schema
from scheduler.tasks import mytask, scheduler

router = APIRouter()


@router.get("/")
async def index():
    return {"ping": "pong"}


@router.get("/jobs", response_model=schema.QueryResponse)
async def get_jobs(verbose: bool = False):
    """get all scheduled jobs"""

    jobs = []
    try:
        job_list = scheduler.get_jobs()
        if job_list:
            jobs = [schema.Job(**task.__getstate__()) for task in job_list]

        if verbose:
            logger.info(jobs)
    except Exception as e:
        logger.exception(e.args)
        return schema.QueryResponse(
            message=f"Failed query {e.args}",
            status_code=0,
            jobs=jobs,
        )

    return schema.QueryResponse(
        message="Successfully query",
        status_code=1,
        jobs=jobs,
    )


@router.get("/job/{id}", response_model=schema.QueryResponse)
async def get_job_by_id(id: Union[int, str, uuid.UUID], verbose: bool = False):
    """get scheduled job by id"""

    jobs = []
    try:
        job = scheduler.get_job(job_id=id)
        if job:
            jobs = [schema.Job(**job.__getstate__())]

        if verbose:
            logger.info(job)
    except Exception as e:
        logger.exception(e.args)
        return schema.QueryResponse(
            message=f"Failed query {e.args}",
            status_code=0,
            jobs=jobs,
        )

    return schema.QueryResponse(
        message="Successfully query",
        status_code=1,
        jobs=jobs,
    )


@router.post("/add", response_model=schema.OperateResponse)
async def add_job(
    msg: str,
    trigger: schema.TriggerEnum,
    trigger_args: Optional[dict],
    id: Union[str, int, uuid.UUID] = None,
    verbose: bool = False,
):
    """create new job"""

    try:
        scheduler.add_job(
            id=id,
            func=mytask,
            kwargs={"msg": msg, "verbose": verbose},
            trigger=trigger.value,
            **trigger_args,
        )
    except Exception as e:
        logger.exception(e.args)
        raise HTTPException(
            status_code=500,
            detail=f"Some internal error happened: {e.args}",
        )
    return schema.OperateResponse(
        message="Successfully add",
        status_code=1,
        type="add",
    )


@router.put("/reschedule/{id}")
async def reschedule_job(res: schema.Rescheduler):
    """update exist job by id"""

    try:
        scheduler.reschedule_job(
            job_id=res.id, trigger=res.trigger.value, **res.trigger_args
        )
    except Exception as e:
        logger.exception(e.args)
        return schema.OperateResponse(
            message=f"Failed reschedule: {e.args}",
            status_code=0,
            type="reschedule",
        )
    return schema.OperateResponse(
        message="Successfully reschedule",
        status_code=1,
        type="reschedule",
    )


@router.put("/pause/{id}")
async def pause_job(id: Union[str, int, uuid.UUID]):
    """pausing """

    try:
        scheduler.pause_job(job_id=id)
    except Exception as e:
        logger.exception(e.args)
        return schema.OperateResponse(
            message=f"Can't find <id:{id}> job",
            status_code=0,
            type="pause",
        )

    return schema.OperateResponse(
        message=f"Successfully pause <id:{id}> job",
        status_code=1,
        type="pause",
    )


@router.put("/resume/{id}")
async def resume_job(id: Union[str, int, uuid.UUID]):
    """resume pausing job by id"""
    try:
        scheduler.resume_job(job_id=id)
    except Exception as e:
        logger.exception(e.args)
        return schema.OperateResponse(
            message=f"Can't find <id:{id}> job",
            status_code=0,
            type="resume",
        )
    return schema.OperateResponse(
        message=f"Successfully resume <id:{id}> job",
        status_code=1,
        type="resume",
    )


@router.delete("/delete/all")
async def delete_all_jobs():
    """delete all exist jobs"""

    try:
        scheduler.remove_all_jobs()
    except Exception:
        return schema.OperateResponse(
            message="there isn't any scheduled job",
            status_code=0,
            type="delete",
        )
    return schema.OperateResponse(
        message="Successfully delete all jobs",
        status_code=1,
        type="delete_all",
    )


@router.delete("/delete/{id}")
async def delete_job(id: Union[str, int, uuid.UUID]):
    """delete exist job by id"""
    try:
        scheduler.remove_job(job_id=id)
    except JobLookupError:
        return schema.OperateResponse(
            message="failed delete",
            status_code=0,
            type="delete",
        )
    return schema.OperateResponse(
        message="Successfully delete",
        status_code=1,
        type="delete",
    )
